package com.glodon.jcloud.increment.shorturl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glodon.jcloud.common.exception.CommonException;
import com.glodon.jcloud.increment.common.enums.SortOrderEnum;
import com.glodon.jcloud.increment.common.pojo.CommonValidList;
import com.glodon.jcloud.increment.common.utils.ShortUrlUtil;
import com.glodon.jcloud.increment.dto.PageableDto;
import com.glodon.jcloud.increment.shorturl.entities.ShortUrl;
import com.glodon.jcloud.increment.shorturl.mapper.ShortUrlMapper;
import com.glodon.jcloud.increment.shorturl.param.*;
import com.glodon.jcloud.increment.shorturl.service.ShortUrlService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * Create Date: 2022/12/12
 *
 * @version: V0.0.1-SNAPSHOT
 * @author: Terry.Li
 * @mail: lib-o@glodon.com
 */
@Slf4j
@Service
public class ShortUrlServiceImpl extends ServiceImpl<ShortUrlMapper, ShortUrl> implements ShortUrlService {

    private static final String regex = "(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]";

    /**
     * 获取短链接分页.
     *
     * @param shortUrlPageParam the shortUrl page param
     * @return the page
     */
    @Override
    public Page<ShortUrl> page(ShortUrlPageParam shortUrlPageParam) {
        QueryWrapper<ShortUrl> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(shortUrlPageParam.getSearchKey())) {
            queryWrapper.lambda().like(ShortUrl::getChainTitle, shortUrlPageParam.getSearchKey());
        }
        if (ObjectUtil.isAllNotEmpty(shortUrlPageParam.getSortField(), shortUrlPageParam.getSortOrder())) {
            SortOrderEnum.validate(shortUrlPageParam.getSortOrder());
            queryWrapper.orderBy(true, shortUrlPageParam.getSortOrder().equals(SortOrderEnum.ASC.getValue()), StrUtil.toUnderlineCase(shortUrlPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByDesc(true, ShortUrl::getCreatedate);
        }
        return this.page(PageableDto.defaultPage(), queryWrapper);
    }

    /**
     * 添加短链接.
     *
     * @param shortUrlAddParam the shortUrl add param
     */
    @Override
    public ShortUrl add(ShortUrlAddParam shortUrlAddParam) {
        ShortUrl shortUrl = BeanUtil.toBean(shortUrlAddParam, ShortUrl.class);
        shortUrl.setChain(ShortUrlUtil.shortUrl(shortUrlAddParam.getTargetUrl()));
        boolean result = this.save(shortUrl);
        return result ? shortUrl : null;
    }

    /**
     * 编辑短链接.
     *
     * @param shortUrlEditParam the shortUrl edit param
     *//**
     * 编辑短链接.
     *
     * @param shortUrlEditParam the shortUrl edit param
     */
    @Override
    public void edit(ShortUrlEditParam shortUrlEditParam) {
        ShortUrl shortUrl = this.queryEntity(shortUrlEditParam.getId());
        BeanUtil.copyProperties(shortUrlEditParam, shortUrl);
        shortUrl.setChain(ShortUrlUtil.shortUrl(shortUrlEditParam.getTargetUrl()));
        this.updateById(shortUrl);
    }

    /**
     * 获取短链接详情.
     *
     * @param id the id
     * @return the shortUrl
     */
    @Override
    public ShortUrl queryEntity(String id) {
        ShortUrl shortUrl = this.getById(id);
        if (ObjectUtil.isEmpty(shortUrl)) {
            throw new CommonException("短链接不存在，id值为：{}", id);
        }
        return shortUrl;
    }

    /**
     * 删除短链接.
     *
     * @param shortUrlIdParamList the shortUrl id param list
     */
    @Override
    public void delete(CommonValidList<ShortUrlIdParam> shortUrlIdParamList) {
        List<String> shortUrlIdList = CollStreamUtil.toList(shortUrlIdParamList, ShortUrlIdParam::getId);
        if (ObjectUtil.isNotEmpty(shortUrlIdList)) {
            // TODO: 查询短链接下的客户端信息，如果存在客户端则不能删除短链接
            this.removeBatchByIds(shortUrlIdList);
        }
    }

    /**
     * 获取短链接详情.
     *
     * @param shortUrlIdParam the shortUrl id param
     * @return the shortUrl
     */
    @Override
    public ShortUrl detail(ShortUrlIdParam shortUrlIdParam) {
        return this.queryEntity(shortUrlIdParam.getId());
    }

    /**
     * 获取短链接跳转地址.
     *
     * @param alias the alias
     * @return the link
     */
    @Override
    public String getLink(String alias) {
        if (ObjectUtil.isNotEmpty(alias)) {
            ShortUrl shortUrl = this.getOne(new QueryWrapper<ShortUrl>().lambda().eq(ShortUrl::getChain, alias).last("limit 1"));
            return ObjectUtil.isNotEmpty(shortUrl) ? shortUrl.getTargetUrl() : StringUtils.EMPTY;
        }
        return null;
    }

    /**
     * View.
     *
     * @param alias the alias
     */
    @Override
    public void view(String alias) {
        if (ObjectUtil.isNotEmpty(alias)) {
            ShortUrl shortUrl = this.getOne(new QueryWrapper<ShortUrl>().lambda().eq(ShortUrl::getChain, alias).last("limit 1"));
            if (ObjectUtil.isNotEmpty(shortUrl)) {
                shortUrl.setViewCount(shortUrl.getViewCount() + 1);
            }
            this.updateById(shortUrl);
        }
    }

    /**
     * 转换文本中短链接.
     *
     * @param shortUrlConvertParam the short url convert param
     * @return the string
     */
    @Override
    public String convert(ShortUrlConvertParam shortUrlConvertParam) {
        ShortUrlConvertParam converted = null;
        if (ObjectUtil.isNotEmpty(shortUrlConvertParam.getContent())) {
            converted = BeanUtil.copyProperties(shortUrlConvertParam, ShortUrlConvertParam.class);
            Pattern p = Pattern.compile(regex);
            Matcher matcher = p.matcher(shortUrlConvertParam.getContent());
            ShortUrl shortUrl = null;
            while (matcher.find()) {
                shortUrl = this.add(new ShortUrlAddParam().setChainTitle(converted.getTitle()).setTargetUrl(matcher.group()));
                if (ObjectUtil.isNotEmpty(shortUrl)) {
                    String original = converted.getContent();
                    if (ObjectUtil.isNotEmpty(original)) {
                        int index = original.indexOf(shortUrl.getTargetUrl());
                        if (index >= 0 && shortUrl.getTargetUrl().length() > 0) {
                            long currentTimeMillis = System.currentTimeMillis();
                            original = original.substring(0, index) + "$"+ currentTimeMillis +"$" + original.substring(index + shortUrl.getTargetUrl().length());
                            converted.setContent(original.replace("$"+ currentTimeMillis +"$", shortUrl.getDomain() + "/" + shortUrl.getChain()));
                        }
                    }
                }
            }
        }
        return ObjectUtil.isNotEmpty(converted) ? converted.getContent() : StringUtils.EMPTY;
    }


}
